package zhh.tangbao.user.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import zhh.tangbao.system.constant.DataStatus;
import zhh.tangbao.system.exception.ServiceException;
import zhh.tangbao.system.utils.UserHolderUtil;
import zhh.tangbao.user.dao.AuthorityDao;
import zhh.tangbao.user.dao.OperateDao;
import zhh.tangbao.user.dao.RoleDao;
import zhh.tangbao.user.dto.ModuleQueryDto;
import zhh.tangbao.user.dto.role.RoleOperateUpdateDto;
import zhh.tangbao.user.dto.role.RoleQueryDto;
import zhh.tangbao.user.entity.Authority;
import zhh.tangbao.user.entity.AuthorityOperate;
import zhh.tangbao.user.entity.Role;
import zhh.tangbao.user.service.RoleService;
import zhh.tangbao.user.vo.*;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author 粥灰灰
 * @version 1.0
 * @created 2022/10/5
 * @Description 描述
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private UserHolderUtil userHolderUtil;

    @Resource
    private RoleDao dao;

    @Autowired
    private OperateDao operateDao;

    @Autowired
    private AuthorityDao authorityDao;


    @Transactional
    @Override
    public int addRole(Role dto) {
        UserVo currentUser = userHolderUtil.getCurrentUser();
        dto.setBaseCreateInfo(currentUser.getId());
        int insert = dao.insert(dto);
        int ai = authorityDao.insertRoleAuthorityRelation(dto.getId(), dto.getAuthorityIds());
        int oi = 0;
        if (CollUtil.isNotEmpty(dto.getOperateIds())) {
            oi = operateDao.insertRoleOperateRelation(dto.getId(), dto.getOperateIds());
        }
        return insert + ai + oi;
    }

    @Override
    public int deleteRole(Long id) {
        return 0;
    }

    @Override
    public int updateRole(Role role) {
        UserVo currentUser = userHolderUtil.getCurrentUser();
        role.setBaseCreateInfo(currentUser.getId());
        return dao.updateById(role);
    }

    @Override
    public Role findById(String id) {
        return null;
    }

    @Override
    public Set<String> getRoleAuthority(Long roleId) {
        return null;
    }

    @Override
    public String getDefaultRoleId(String roleType) {
        return dao.getDefaultRoleId(roleType);
    }

    @Override
    public int updateDefaultRoleId(String roleType, Long newRoleId) {
        return dao.updateDefaultRoleId(roleType, newRoleId);
    }

    @Override
    public List<RoleTypeVo> getRoleType() {
        return dao.getRoleType();
    }

    @Override
    public List<AuthorityOperate> getRoleOperate(String module, boolean openAllFunction) {
        String roleId = null;
        if (!openAllFunction) {
            UserVo currentUser = userHolderUtil.getCurrentUser();
            roleId = currentUser.getRoleId();
        }
        return operateDao.listOperateByRoleIdAndAuthorityCode(roleId, module);
    }

    @Override
    public List<ModuleOptionVo> getModuleOption(ModuleQueryDto dto) {
        return operateDao.getModuleOption(dto);
    }

    @Override
    public ModuleInfoVo getModuleOperates(String moduleCode) {
        ModuleInfoVo module = operateDao.getModuleInfo(new ModuleQueryDto().setModuleCode(moduleCode));
        Assert.notNull(module, "模块信息不存在");
        QueryWrapper<AuthorityOperate> query = new QueryWrapper<>();
        if (StrUtil.isNotBlank(moduleCode)) {
            query.eq("authority_code", moduleCode);
        }
        module.setModuleOperates(operateDao.selectList(query));
        return module;
    }

    @Override
    public Page<Role> page(RoleQueryDto dto) {
        Page<Role> page = new Page<>(dto.getPageNum(), dto.getPageSize());
        QueryWrapper<Role> query = new QueryWrapper<>();
        query.eq("data_status", DataStatus.ENABLE);
        if (StrUtil.isNotBlank(dto.getRoleName())) {
            query.like("role_name", dto.getRoleName());
        }
        if (StrUtil.isNotBlank(dto.getRoleId())) {
            query.eq("id", dto.getRoleId());
        }
        return dao.selectPage(page, query);
    }

    @Transactional
    @Override
    public int batchDelete(List<String> ids) {
        Assert.notEmpty(ids, "未选择删除的角色");
        if (ids.contains(userHolderUtil.getCurrentUser().getRoleId())) {
            throw new ServiceException("无法删除当前登录账号所属的角色");
        }
        Role update = new Role();
        update.setUpdateInfo(userHolderUtil.getCurrentUser().getId(), new Date(), DataStatus.DELETED);
        int br = dao.update(update, new QueryWrapper<Role>().in("id", ids));
        int ai = authorityDao.deleteRoleAuthority(ids);
        int oi = operateDao.deleteRoleOperate(ids);
        return br + ai + oi;
    }

    @Override
    public List<OperateTreeNodeVo> getRoleOperateTree(String roleId) {
        // 获取功能模块权限码，也就是模块码
        List<OperateTreeNodeVo> as = authorityDao.listOperateTreeNodeVosByRoleId(roleId);
        if (CollUtil.isEmpty(as)) {
            return as;
        }
        Map<String, OperateTreeNodeVo> aMap = as.stream().collect(Collectors.toMap(OperateTreeNodeVo::getId, Function.identity()));
        List<AuthorityOperate> authorityOperates = operateDao.listOperateByRoleIdAndAuthorityCode(roleId, null);
        if (CollUtil.isEmpty(authorityOperates)) {
            return as;
        }
        for (int i = 0; i < authorityOperates.size(); i++) {
            AuthorityOperate ao = authorityOperates.get(i);
            OperateTreeNodeVo op = aMap.get(ao.getAuthorityCode());
            if (null == op) {
                continue;
            }
            if (CollUtil.isEmpty(op.getChildren())) {
                op.setChildren(Lists.newArrayList());
            }
            op.getChildren().add(new OperateTreeNodeVo(ao.getOperateCode(), ao.getOperateName()));
        }
        return as;
    }

    @Override
    public List<String> getRoleAlreadyHadOperateTree(String roleId) {
        List<String> result = Lists.newArrayList();
        // 模块权限
        List<OperateTreeNodeVo> as = authorityDao.listOperateTreeNodeVosByRoleId(roleId);
        if (CollUtil.isEmpty(as)) {
            return result;
        }
        for (int i = 0; i < as.size(); i++) {
            result.add(as.get(i).getId());
        }
        // 操作权限
        List<AuthorityOperate> authorityOperates = operateDao.listOperateByRoleIdAndAuthorityCode(roleId, null);
        if (CollUtil.isEmpty(authorityOperates)) {
            return result;
        }
        for (int i = 0; i < authorityOperates.size(); i++) {
            result.add(authorityOperates.get(i).getOperateCode());
        }
        return result;
    }

    @Override
    public List<OperateTreeNodeVo> getOperateTree() {
        List<Authority> authorities = authorityDao.selectList(new QueryWrapper<Authority>().eq("data_status", DataStatus.ENABLE));
        if (CollUtil.isEmpty(authorities)) {
            return Lists.newArrayList();
        }
        Map<String, OperateTreeNodeVo> aMap = Maps.newHashMap();
        for (int i = 0; i < authorities.size(); i++) {
            Authority authority = authorities.get(i);
            OperateTreeNodeVo node = new OperateTreeNodeVo(authority.getAuthorityCode(), authority.getAuthorityName(), authority.getId(), false);
            aMap.put(authority.getAuthorityCode(), node);
        }
        List<AuthorityOperate> authorityOperates = operateDao.selectList(null);
        if (CollUtil.isEmpty(authorityOperates)) {
            return Lists.newArrayList();
        }
        for (int i = 0; i < authorityOperates.size(); i++) {
            AuthorityOperate ao = authorityOperates.get(i);
            OperateTreeNodeVo node = new OperateTreeNodeVo(ao.getOperateCode(), ao.getOperateName(), ao.getId(), true);
            OperateTreeNodeVo vo = aMap.get(ao.getAuthorityCode());
            if (null != vo) {
                vo.getChildren().add(node);
            }
        }
        return Lists.newArrayList(aMap.values());
    }

    @Transactional
    @Override
    public int updateRoleOperate(RoleOperateUpdateDto dto) {
        UserVo currentUser = userHolderUtil.getCurrentUser();
        Assert.notEquals(currentUser.getRoleId(), dto.getRoleId(), "无法修改当前登录账号所属角色操作权限");
        Assert.notEmpty(dto.getAuthorities(), "必须赋予角色任一权限");
        Role role = dao.selectById(dto.getRoleId());
        Assert.notNull(role, "角色信息不存在");
        int d = authorityDao.deleteRoleAuthorityRelation(dto.getRoleId());
        int i = authorityDao.insertRoleAuthorityRelation(dto.getRoleId(), dto.getAuthorities());
        int d1 = operateDao.deleteRoleOperateRelation(dto.getRoleId());
        int i1 = 0;
        if (CollUtil.isNotEmpty(dto.getOperates())) {
            i1 = operateDao.insertRoleOperateRelation(dto.getRoleId(), dto.getOperates());
        }
        role.setUpdateInfo(currentUser.getId());
        dao.updateById(role);
        return d + d1 + i + i1;
    }
}
